package org.example.gradleauth.security.filter;

import org.example.gradleauth.model.dto.LoginUserDto;
import org.example.gradleauth.security.handler.SecurityAuthenticationFailureHandler;
import org.example.gradleauth.security.handler.SecurityAuthenticationSuccessHandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import gradle.common.core.context.SpringApplicationContext;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;

import java.io.IOException;

/**
 * 参考 org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter
 * 登录地址过滤拦截器
 */
public class SecurityLoginFilter extends AbstractAuthenticationProcessingFilter {

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 1.利用过滤器拦截 url
     * 2.设置 AuthenticationManager
     * 3.设置登录失败处理器
     * 4.设置登录成功处理器
     */
    public SecurityLoginFilter() {
        super(new AntPathRequestMatcher("/login", "POST"));
        // 获取 AuthenticationManager
        AuthenticationManager authenticationManager = SpringApplicationContext.getBean(AuthenticationManager.class);
        // 设置 AuthenticationManager
        setAuthenticationManager(authenticationManager);
        // 设置登录失败处理器
        this.setAuthenticationFailureHandler(new SecurityAuthenticationFailureHandler());
        // 设置登录成功处理器
        this.setAuthenticationSuccessHandler(new SecurityAuthenticationSuccessHandler());
    }

    /**
     * 尝试身份验证
     */
    @Override
    public Authentication attemptAuthentication(HttpServletRequest request,
                                                HttpServletResponse response)
            throws AuthenticationException, IOException {

        LoginUserDto loginRequest = objectMapper.readValue(request.getInputStream(), LoginUserDto.class);
        UsernamePasswordAuthenticationToken token =
                new UsernamePasswordAuthenticationToken(loginRequest.getUsername(), loginRequest.getPassword());

        return getAuthenticationManager().authenticate(token);
    }
}